package com.atguigu.gulimallcart.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.atguigu.common.utils.R;
import com.atguigu.gulimallcart.feign.ProductFeignService;
import com.atguigu.gulimallcart.interceptor.CartInterceptor;
import com.atguigu.gulimallcart.service.CartService;
import com.atguigu.gulimallcart.to.UserInfoTo;
import com.atguigu.gulimallcart.vo.Cart;
import com.atguigu.gulimallcart.vo.CartItem;
import com.atguigu.gulimallcart.vo.SkuInfoVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

@Service
public class CartServiceImpl implements CartService {

    private final String CART_PREFIX = "gulimall:cart:";

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private ThreadPoolExecutor executor;

    @Autowired
    private ProductFeignService productFeignService;

    /**
     * 添加商品到购物车
     */
    @Override
    public CartItem addToCart(Long skuId, Integer num) throws ExecutionException, InterruptedException {
        BoundHashOperations<String, Object, Object> operations = getCartOps();

        String res = (String) operations.get(skuId.toString());

        if (StringUtils.isEmpty(res)) {
            // 购物车中没有，添加新的商品
            CartItem cartItem = new CartItem();
            CompletableFuture<Void> cartBase = CompletableFuture.runAsync(() -> {
                // 1 添加新商品
                R skuinfo = productFeignService.getSkuinfo(skuId);
                SkuInfoVo skuInfoEntity = skuinfo.getData("skuInfo", new TypeReference<SkuInfoVo>() {
                });
                cartItem.setPrice(skuInfoEntity.getPrice());
                cartItem.setTitle(skuInfoEntity.getSkuTitle());
                cartItem.setSkuId(skuId);
                cartItem.setCheck(true);
                cartItem.setCount(num);
                cartItem.setImage(skuInfoEntity.getSkuDefaultImg());
            }, executor);

            CompletableFuture<Void> cartAttr = CompletableFuture.runAsync(() -> {
                // 2 远程查询sku对应的属性
                List<String> values = productFeignService.getSkuSaleAttrValues(skuId);
                cartItem.setSkuAttrValues(values);
            }, executor);

            CompletableFuture.allOf(cartAttr, cartBase).get();

            operations.put(skuId.toString(), JSON.toJSONString(cartItem));

            return cartItem;
        }

        // 购物车中有，添加数量
        CartItem cartItem = JSON.parseObject(res, CartItem.class);
        cartItem.setCount(cartItem.getCount() + num);
        operations.put(skuId.toString(), JSON.toJSONString(cartItem));
        return cartItem;
    }


    @Override
    public CartItem getCartItem(Long skuId) {
        BoundHashOperations<String, Object, Object> cartOps = getCartOps();

        String str = (String) cartOps.get(skuId.toString());
        CartItem cartItem = JSON.parseObject(str, CartItem.class);

        return cartItem;
    }

    @Override
    public Cart getCart() throws ExecutionException, InterruptedException {
        UserInfoTo userInfoTo = CartInterceptor.threadLocal.get();
        Cart cart = new Cart();

        if (userInfoTo.getUserId() != null) {
            // 1 登录
            String userId = this.CART_PREFIX + userInfoTo.getUserId();
            String userKey = this.CART_PREFIX + userInfoTo.getUserKey();

            // 2 如果临时购物车里面的数据还没有合并，就合并
            List<CartItem> cartItems = getCartItems(userKey);
            if (cartItems != null && cartItems.size() > 0) {
                for (CartItem cartItem : cartItems) {
                    addToCart(cartItem.getSkuId(), cartItem.getCount());
                }

                // 清空零四购购物车
                clearCart(userKey);
            }

            // 3 查询合并后的结果并返回
            List<CartItem> items = getCartItems(userId);
            cart.setItems(items);

        } else {
            // 没登陆
            String userKey = this.CART_PREFIX + userInfoTo.getUserKey();
            List<CartItem> cartItems = getCartItems(userKey);
            cart.setItems(cartItems);
        }

        return cart;
    }

    @Override
    public void clearCart(String userKey) {
        redisTemplate.delete(userKey);
    }

    @Override
    public void checkItem(Long skuId, Integer check) {
        CartItem cartItem = getCartItem(skuId);
        cartItem.setCheck(check > 0);
        String s = JSON.toJSONString(cartItem);
        getCartOps().put(skuId.toString(), s);
    }

    @Override
    public void changeItemCount(Long skuId, Integer num) {
        CartItem cartItem = getCartItem(skuId);
        cartItem.setCount(num);
        String s = JSON.toJSONString(cartItem);
        getCartOps().put(skuId.toString(), s);
    }

    @Override
    public void deleteItem(Long skuId) {
        getCartOps().delete(skuId.toString());
    }

    /**
     * 获取用户购物车中选中的商品
     *
     * @return 选中的商品
     */
    @Override
    public List<CartItem> getUserCartItems() {
        UserInfoTo userInfoTo = CartInterceptor.threadLocal.get();
        if (userInfoTo == null) {
            return null;
        } else {
            String userKey = this.CART_PREFIX + userInfoTo.getUserId();
            List<CartItem> cartItems = getCartItems(userKey);

            // 获取所有选中的商品
            List<CartItem> collect = cartItems.stream().filter(CartItem::getCheck)
                    .map(cartItem -> {
                        // 查询最新价格
                        R price = productFeignService.getPrice(cartItem.getSkuId());
                        String data = (String) price.get("data");
                        cartItem.setPrice(new BigDecimal(data));

                        return cartItem;
                    }).collect(Collectors.toList());

            return collect;
        }
    }

    /**
     * 根据用户（登录/未登录） key 获取购物项，
     */
    private List<CartItem> getCartItems(String userKey) {
        BoundHashOperations<String, Object, Object> cartOps = redisTemplate.boundHashOps(userKey);
        List<Object> values = cartOps.values();
        if (values != null && values.size() > 0) {
            List<CartItem> carItems = values.stream().map(value -> {

                return JSON.parseObject((String) value, CartItem.class);
            }).collect(Collectors.toList());
            return carItems;
        }
        return null;
    }

    /**
     * 获取指定用户的购物车操作对象
     */
    private BoundHashOperations<String, Object, Object> getCartOps() {
        BoundHashOperations<String, Object, Object> operations;

        UserInfoTo userInfoTo = CartInterceptor.threadLocal.get();
        String cartKey = this.CART_PREFIX;
        if (userInfoTo.getUserId() != null) {
            cartKey = cartKey + userInfoTo.getUserId();
        } else {
            cartKey = cartKey + userInfoTo.getUserKey();
        }

        operations = redisTemplate.boundHashOps(cartKey);
        return operations;
    }
}
